# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import re

from .parse_config import ParseConfig

from .raw_text import RawText
from .raw_html import RawHtml
from .code_block import CodeBlock

from .bold import Bold
from .inline_code import InlineCode
from .italic import Italic
from .strikethrough import Strikethrough
from .subscript import Subscript
from .superscript import Superscript
from .underline import Underline

from .link import Link

from .list_base import ListBase


class Parser(object):
    """docstring for Parse"""
    def __init__(self, content):
        super(Parser, self).__init__()
        self.content = content
        self._caches = {}
        self.paragraphs = []
        self.paragraph_tag = 'p'
        self.paragraph_class = None

    @property
    def caches(self):
        return self._caches

    def _split_paragraph(self):
        '''分段落'''
        self.paragraphs = re.split(r'\n{2,}', self.content)

    def _toHtml(self):
        '''输出为html'''
        while bool(self._caches):
            _k, _v = self._caches.popitem()
            if _k in self.content:
                self.content = self.content.replace(_k, _v)
            else:
                self._caches[_k] = _v
        return self.content

    def parse(self):
        # 0. 统一换行符为 \n
        self._unify_line_sep()
        # 1. 读取配置
        self._read_config()
        # 1. 处理raw字符串文本
        self._p_raw_text()
        # 2. 处理raw字符串html
        self._p_raw_html()
        # 3. 处理代码块
        self._p_code_block()
        # 4. 分段
        self._split_paragraph()
        p_single_funcs = [
            self._p_link, # 12. 链接
            self._p_blod, # 5. 处理粗体
            self._p_inline_code, # 6. 处理行内代码
            self._p_italic, # 7. 处理斜体
            self._p_strikethrough, # 8. 处理删除线
            self._p_subscript, # 9. 处理下标
            self._p_superscript, # 10. 处理上标
            self._p_underline, # 11. 处理下划线
        ]
        i = 0
        for _temp in self.paragraphs:
            for _func in p_single_funcs:
                p = self.paragraphs[i]
                _func(p, i)
            # 处理列表
            p = self.paragraphs[i]
            if ListBase.isList(p):
                self._p_list(p, i)
            # 处理列表转义
            if re.match(r'^\\(\.|\*)', p):
                self.paragraphs[i] = p[1:]
            i += 1
        # merge all paragraphs together
        p_class = ''
        if bool(self.paragraph_class):
            p_class = ' class="' + self.paragraph_class + '"'
        self.content = '\n'.join(['<' + self.paragraph_tag + p_class + '>' + _p + '</' + self.paragraph_tag + '>' for _p in self.paragraphs])
        return self._toHtml()

    def _unify_line_sep(self):
        '''统一换行符为 \n'''
        self.content = self.content.replace('\r\n', '\n').replace('\r', '\n')

    def _read_config(self):
        cp = ParseConfig(self.content)
        _cfgs = cp.read()
        self.paragraph_tag = _cfgs['paragraph_tag']
        self.paragraph_class = _cfgs['paragraph_class']
        self.content = cp.content

    def _p_raw_text(self):
        rt = RawText(self.content)
        ret = rt.parse()
        self._caches.update(ret['cache'])
        self.content = ret['content']

    def _p_raw_html(self):
        rh = RawHtml(self.content)
        ret = rh.parse()
        self._caches.update(ret['cache'])
        self.content = ret['content']

    def _p_code_block(self):
        cb = CodeBlock(self.content)
        ret = cb.parse()
        self._caches.update(ret['cache'])
        self.content = ret['content']
    
    def _p_blod(self, paragraph, paragraph_index):
        b = Bold(paragraph, paragraph_index)
        ret = b.parse()
        self._caches.update(ret['cache'])
        self.paragraphs[paragraph_index] = ret['content']

    def _p_inline_code(self, paragraph, paragraph_index):
        ic = InlineCode(paragraph, paragraph_index)
        ret = ic.parse()
        self._caches.update(ret['cache'])
        self.paragraphs[paragraph_index] = ret['content']

    def _p_italic(self, paragraph, paragraph_index):
        i = Italic(paragraph, paragraph_index)
        ret = i.parse()
        self._caches.update(ret['cache'])
        self.paragraphs[paragraph_index] = ret['content']
    
    def _p_strikethrough(self, paragraph, paragraph_index):
        s = Strikethrough(paragraph, paragraph_index)
        ret = s.parse()
        self._caches.update(ret['cache'])
        self.paragraphs[paragraph_index] = ret['content']

    def _p_subscript(self, paragraph, paragraph_index):
        sub_s = Subscript(paragraph, paragraph_index)
        ret = sub_s.parse()
        self._caches.update(ret['cache'])
        self.paragraphs[paragraph_index] = ret['content']

    def _p_superscript(self, paragraph, paragraph_index):
        super_s = Superscript(paragraph, paragraph_index)
        ret = super_s.parse()
        self._caches.update(ret['cache'])
        self.paragraphs[paragraph_index] = ret['content']

    def _p_underline(self, paragraph, paragraph_index):
        ul = Underline(paragraph, paragraph_index)
        ret = ul.parse()
        self._caches.update(ret['cache'])
        self.paragraphs[paragraph_index] = ret['content']

    def _p_link(self, paragraph, paragraph_index):
        _lnk = Link(paragraph, paragraph_index)
        ret = _lnk.parse()
        self._caches.update(ret['cache'])
        self.paragraphs[paragraph_index] = ret['content']

    def _p_list(self, paragraph, paragraph_index):
        _lst = ListBase(paragraph, paragraph_index)
        ret = _lst.parse()
        self._caches.update(ret['cache'])
        self.paragraphs[paragraph_index] = ret['content']